package org.onion.pattern.event.spring.outbox;


import lombok.extern.slf4j.Slf4j;
import org.onion.pattern.event.outbox.EventOutbox;
import org.onion.pattern.event.outbox.annotation.Outbox;
import org.onion.pattern.event.spring.listener.EventListenerHandler;
import org.onion.pattern.event.spring.signal.EventPublishedEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.event.ContextClosedEvent;
import org.springframework.context.event.EventListener;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.stereotype.Component;
import org.springframework.transaction.support.TransactionSynchronization;
import org.springframework.transaction.support.TransactionSynchronizationManager;

/**
 * 本地消息表
 */
@Component
@Slf4j
public class OutboxEventHandler implements EventListenerHandler {

    @Autowired
    private EventOutbox eventOutBox;

//    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();

//    static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
//
//    static {
//        JavaTimeModule javaTimeModule = new JavaTimeModule();
////        javaTimeModule.addDeserializer(Duration.class, DurationDeserializer.INSTANCE);
////        javaTimeModule.addSerializer(Duration.class, DurationSerializer.INSTANCE);
////        javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeRoundDownSerializer());
//        javaTimeModule.addSerializer(LocalDateTime.class, new JsonSerializer<LocalDateTime>() {
//            @Override
//            public void serialize(LocalDateTime value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
//                if (value == null) {
//                    gen.writeNull();
//                    return;
//                }
//                // 格式化日期时间
//                String formattedDateTime = value.format(formatter);
//                gen.writeString(formattedDateTime);
//            }
//        });
//
//        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm");
//        javaTimeModule.addSerializer(LocalTime.class, new LocalTimeSerializer(formatter));
//        javaTimeModule.addDeserializer(LocalTime.class, new LocalTimeDeserializer(formatter));
//
//        OBJECT_MAPPER.setTimeZone(TimeZone.getTimeZone(ZoneId.of("Asia/Shanghai")));
//        OBJECT_MAPPER.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
//        OBJECT_MAPPER.setSerializationInclusion(JsonInclude.Include.NON_NULL);
//        OBJECT_MAPPER.registerModule(javaTimeModule);
//        OBJECT_MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
//    }

    /**
     * 重动发件箱
     */
    @EventListener(ApplicationReadyEvent.class)
    void start() {
        eventOutBox.start();
    }

    /**
     * 刷新发件箱
     */
    @EventListener(EventPublishedEvent.class)
    public void onApplicationEvent(EventPublishedEvent event) {
        //todo 按组刷新
        eventOutBox.flush();
    }

    /**
     * 关闭发件箱
     */
    @EventListener(ContextClosedEvent.class)
    public void onApplicationEvent(ContextClosedEvent event) {
        eventOutBox.shutdown();
    }

    @Override
    public boolean support(Object event) {
        Outbox annotation = AnnotationUtils.findAnnotation(event.getClass(), Outbox.class);
        return annotation != null;
    }

    @Override
    public void handle(Object event) {
        eventOutBox.delivery(event);
        //todo 按组刷新
        //自动刷新
        if (TransactionSynchronizationManager.isSynchronizationActive() && TransactionSynchronizationManager.isActualTransactionActive()) {
            //当前上下文存在事务
            TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
                @Override
                public void afterCompletion(int status) {
                    if (status == 1) { //回滚后处理
                        return;
                    }
                    eventOutBox.flush();
                }
            });
        } else {
            eventOutBox.flush();
        }
    }

    @Override
    public int getOrder() {
        return HIGHEST_PRECEDENCE;
    }


}
